/*
 * Dispatcher.java    0.0.1    08/dic/2009
 * 
 * Copyright (c) 2009 mentalsmash.org
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * The use of the Apache License does not indicate that this project is
 * affiliated with the Apache Software Foundation.
 */ 
package org.mentalsmash.tazio.transparency.interfaces;

import java.io.Serializable;
import java.util.Set;

import org.mentalsmash.tazio.transparency.commons.messages.TazioMessage;

/**
 * A class implementing the Dispatcher interfaces has the task of accepting the registration 
 * of {@link InputMessageListener}s that want to be notified of incoming subclasses of 
 * {@link Serializable} encapsulated as the payload of an incoming {@link TazioMessage}.
 * <p>
 * This class contains the list of components interested to each incoming message and 
 * provides a method that dispatches the new arrived subclass of TazioMessage to each of 
 * the interested listeners.
 * </p>
 * <p>
 * When a message is received, the dispatcher's <code>handleMessage</code> will be invoked, 
 * the list of listeners for the received message will be checked and the payload will be 
 * dispatched to them by invoking their <code>handleMessage</code> method.
 * </p>
 * <p>
 * This class also provides methods to both register to and unregister from the 
 * dispatching table.
 * </p>
 * 
 * @version 0.0.1	08/dic/2009
 * @author Enrico Savioli <savioli.enrico@gmail.com>
 */
public interface Dispatcher {
	
	/**
	 * This method is invoked when a new message is received and its has to be computed 
	 * by a component of the system which is listening for incoming messages of a certain 
	 * type.
	 * <p>
	 * This method will accept a {@link TazioMessage} as an input parameter, retrieve its 
	 * payload, check its list of listeners for components interested in the specific type 
	 * of message and notify them by invoking the <code>handleMessage</code> method on each 
	 * one of them.
	 * </p>
	 * 
	 * @param message	the {@link TazioMessage} that has to be dispatched into the system 
	 * 					to have its answer computed.
	 * @return			the answer to the received {@link TazioMessage}.
	 */
	TazioMessage handleMessage(TazioMessage message);
	
	/**
	 * This method has to be invoked by a component interested in a specific type of message.
	 * <p>
	 * The {@link InputMessageListener} passed as a parameter will be added to the list of 
	 * listeners for the specified message type.
	 * </p>
	 * 
	 * @param <T>		a subclass of {@link Serializable}. 
	 * @param msgClass	the type of message the listener is interested into.
	 * @param listener	the {@link InputMessageListener listener} that will be notified when 
	 * 					a message of the specified type is received.
	 */
	void register(Class<? extends Serializable> msgClass, InputMessageListener listener);
	
	/**
	 * This method has to be invoked by a component that wants to be removed from the 
	 * listeners of a message.
	 * <p>
	 * The {@link InputMessageListener} passed as a parameter will be removed from the list 
	 * of listeners for the specified message type.
	 * </p>
	 * 
	 * 
	 * @param <T>		a subclass of {@link Serializable}.
	 * @param msgClass	the type of message the listener is no more interested into.
	 * @param listener	the {@link InputMessageListener listener} that will be removed from 
	 * 					the list of objects interested in messages of the specified type.
	 */
	void unregister(Class<? extends Serializable> msgClass, InputMessageListener listener);
	
	/**
	 * This method is public due to test purposes, it allows to retrieve the set of 
	 * {@link InputMessageListener}s interested into a specific message class provided as 
	 * an input parameter.
	 * 
	 * @param msgClass	the class for which the set of listeners has to be retrieved.
	 * @return			the set of {@link InputMessageListener}s interested in the specified 
	 * 					class.
	 */
	Set<InputMessageListener> listenersOf(Class<? extends Serializable> msgClass);
	
}
